import json, os
from mongoengine import StringField, DateTimeField, ListField
from utils.decorators import cached_property
from utils.mongoengine import Document
from app.database import BASE_DB
from app.user.models.permission import Permission


class Role(Document):
    _model_desc_ = 'role'
    name = StringField(required=True)
    key = StringField(required=False)
    desc = StringField(required=False)
    _permissions = ListField(StringField())
    meta = {'strict': True, 'db_alias': BASE_DB}

    @cached_property
    def permissions(self):
        return list(Permission.objects(id__in=self._permissions))

    def get_permissions_by_casbin(self):
        from utils.perm import e
        all_perms = e.get_permissions_for_user(self.key)
        perms = [x for x in all_perms if x[3] == self.enterprise_id]
        return [Permission.objects.get(content=i[1], action=i[2]) for i in perms]

    def set_permissions(self, permissions):
        permissions = Permission.objects(id__in=permissions)
        self._permissions = [str(perm.id) for perm in permissions]
        self.save()
        dom = self.enterprise_id
        from utils.perm import e, reset_enforcer
        # e.get_permissions_for_user_in_domain(self.key, dom) # todo dom下的权限存在bug
        ori_permissions = e.get_permissions_for_user(self.key)
        ori_permissions_dict = {str(k): k for k in ori_permissions if k[3] == dom}
        permission_list = [(self.key, p.content, p.action, dom) for p in permissions]
        permission_list_dict = {str(k): k for k in permission_list}

        for line_key in (set(ori_permissions_dict.keys()) - (
                set(ori_permissions_dict.keys()) & set(permission_list_dict.keys()))):
            line = ori_permissions_dict[line_key]
            e.remove_policy(line[0], line[1], line[2], line[3])
        for perm_key in (set(permission_list_dict.keys()) - (
                set(ori_permissions_dict.keys()) & set(permission_list_dict.keys()))):
            line = permission_list_dict[perm_key]
            e.add_policy(line[0], line[1], line[2], line[3])
        for perm_key in (set(ori_permissions_dict.keys()) & set(permission_list_dict.keys())):
            line = permission_list_dict[perm_key]
            print(line)
            print(e.enforce(line[0], line[1], line[2], line[3]))
        self.clear_cached_property('permissions')
        reset_enforcer()

    @classmethod
    def load_from_json(cls):
        path = os.path.join(os.path.dirname(__file__), os.path.split(__file__)[1].replace('.py', '.json'))
        f = open(path, 'r')
        s = json.loads(f.read())
        res = []
        for item in s:
            res.append(cls(**item))
        return res

    @classmethod
    def load_perms_from_json(cls, enterprise_id, roles):
        permission_file_name = 'role_permissions.json'
        path = os.path.join(os.path.dirname(__file__), permission_file_name)
        f = open(path, 'r')
        s = json.loads(f.read())
        f.close()
        if not roles:
            roles = list(s.keys())
        else:
            roles = roles.split(',')
        for k in roles:
            role = Role.across_objects(enterprise_id=enterprise_id, key=k).first()
            if role:
                pids = [p.id for p in Permission.objects(id__in=s[k])]
                role.set_permissions(pids)
